package com.zuosh.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zuosh.common.Result;
import org.apache.commons.lang.RandomStringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;

/**
 * 对象随机属性生成工具
 * Created by zuoshuai on 2017/4/13.
 */
public class RandomClassUtil {

    /**
     * 泛型的class支持
     *
     * @param typeReference
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     * @throws InvocationTargetException
     */
//    public static <T> T generateClass(TypeReference typeReference) throws IllegalAccessException, InstantiationException, ClassNotFoundException, InvocationTargetException {
//        Type type = typeReference.getType();
//        Method[] declaredMethods = aClass.getDeclaredMethods();
//        Field.setAccessible(declaredMethods, true);
//        for (Method method : declaredMethods) {
//            //1.handle basic fields
//            generateMethodValue(o, method);
//        }
//        return o;
//    }

    /**
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T generateClass(Class<T> clazz) throws IllegalAccessException, InstantiationException, ClassNotFoundException, InvocationTargetException {
        String simpleName = clazz.getName();
        Class<?> aClass = Class.forName(simpleName);
        T o = (T) aClass.newInstance();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        Field.setAccessible(declaredMethods, true);
        for (Method method : declaredMethods) {
            //1.handle basic fields
            generateMethodValue(o, method);
        }
        return o;
    }

    /**
     * @param simpleName
     * @param <T>
     * @return
     */
    public static <T> T generateClass(String simpleName) throws IllegalAccessException, InstantiationException, ClassNotFoundException, InvocationTargetException {
        Class<?> aClass = Class.forName(simpleName);
        T o = (T) aClass.newInstance();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        Field.setAccessible(declaredMethods, true);
        for (Method method : declaredMethods) {
            //1.handle basic fields
            generateMethodValue(o, method);
        }
        return o;
    }

    private static <T> void generateMethodValue(T o, Method method) throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        if (method.getName().indexOf("set") != -1) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            Object[] objects = new Object[parameterTypes.length];//对象数组
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> parameterType = parameterTypes[i];
                String name = parameterType.getName();
                List<Class> methodGenericParameterTypes = GenericsUtils.getMethodGenericParameterTypes(method, i);//类型
                //含有泛型参数,可能是集合对象
                if (methodGenericParameterTypes.size() > 0) {
                    //该参数是泛型
                    // TODO: 2017/4/21 处理循环类型 
                    objects[i] = handleCollectionType(parameterType, methodGenericParameterTypes);
                    //
                } else {
                    //基本类型
                    objects[i] = ClassType.getTypeAndSetValue(name);
                }
            }
            try {
                method.invoke(o, objects);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException, InvocationTargetException {
//        Person person = generateClass(Person.class);
//        System.out.println(JSON.toJSONString(person));
//        Result result = generateClass(Result.class);
//        System.out.println(JSON.toJSON(result));
//        Result<Person> result1=new Result<>();
        generateClass("com.zuosh.common.Result<com.zuosh.utils.Person>");
    }

    /**
     * 获取map等集合类型 并设置类型
     */
    public static Object handleCollectionType(Class classType, List<Class> methodGenericParameterTypes) throws IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException {
        if (Map.class.isAssignableFrom(classType)) {
            Map map = new HashMap();
            //
            if (methodGenericParameterTypes.size() != 2) {
                System.out.println("===map 函数 错误===");
                return null;
            }
            Object key = generateClass(methodGenericParameterTypes.get(0));
            Object value = generateClass(methodGenericParameterTypes.get(1));
            //
            map.put(key, value);
            return map;
        } else if (List.class.isAssignableFrom(classType)) {
            List list = new ArrayList();
            Object o = generateClass(methodGenericParameterTypes.get(0));
            list.add(o);
            return list;
        } else if (Set.class.isAssignableFrom(classType)) {
            Set set = new HashSet();
            Object o = generateClass(methodGenericParameterTypes.get(0));
            set.add(o);
            return set;
        } else {
            return null;
        }
    }


//    interface HandleMethodData {
//        void handleData()
//    }

    //类型枚举
    enum ClassType {
        INTEGER("int,java.lang.Integer"),
        STRING("java.lang.String"), LONG("long,java.lang.Long"), BYTE("byte,java.lang.Byte"), SHORT("short,java.lang.Short"),
        CHAR("char,java.lang.Character"), DOUBLE("double,java.lang.Double"), FLOAT("float,java.lang.Float"), DATE("java.util.Date"),
        BOOLEAN("java.lang.Boolean,boolean");
        private String value;

        /**
         * 获取类型
         *
         * @param value
         * @return
         */

        static Object getTypeAndSetValue(String value) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {
            if (INTEGER.getValue().indexOf(value) != -1) {
                return new Integer(new Random().nextInt(10000));
            }
            if (LONG.getValue().indexOf(value) != -1) {
                return new Long(new Random().nextLong());
            }
            if (BYTE.getValue().indexOf(value) != -1) {
                return new Byte(new RandomStringUtils().random(2));
            }
            if (SHORT.getValue().indexOf(value) != -1) {
                return (short) (new Random().nextInt(2));
            }
            if (CHAR.getValue().indexOf(value) != -1) {
                return new RandomStringUtils().random(3);
            }
            if (DOUBLE.getValue().indexOf(value) != -1) {
                return new Double(new Random().nextDouble());
            }
            if (FLOAT.getValue().indexOf(value) != -1) {
                return new Float(new Random().nextFloat());
            }
            if (STRING.getValue().indexOf(value) != -1) {
                return new RandomStringUtils().randomAlphanumeric(5);
            }
            if (BOOLEAN.getValue().indexOf(value) != -1) {
                return new Boolean(true);
            }
            if (DATE.getValue().indexOf(value) != -1) {
                return new Date();
            }
            //处理其他对象类型
            return generateClass(value);
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        ClassType(String value) {
            this.value = value;
        }
    }
}
